#include <stb/stb_image.h>
#include "Texture.h"
#include "render_v1.h"

hxe::Texture::Texture(std::string path, std::string type)
{
    bindType = GL_TEXTURE_2D;
    glGenTextures(1, &textureId);
    glBindTexture(bindType, textureId);

    glTexParameteri(bindType, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(bindType, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(bindType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(bindType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    unsigned char *data;
    if (loadImage(path, &data))
    {
        glTexImage2D(bindType, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(bindType);
        freeImage(data);
    }

    this->type = type;
}


hxe::Texture::Texture(std::vector<std::string> faces)
{
    bindType = GL_TEXTURE_CUBE_MAP;
    glGenTextures(1, &textureId);
    glBindTexture(bindType, textureId);

    for (unsigned int i = 0; i < faces.size(); i++)
    {
        unsigned char *data;
        if (loadImage(faces[i], &data))
        {
            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
            freeImage(data);
        }
    }
    glTexParameteri(bindType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(bindType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(bindType, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(bindType, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(bindType, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);

    this->type = "cubemapTexture";
}

hxe::Texture::~Texture()
{
    glDeleteTextures(1, &textureId);
}

unsigned int hxe::Texture::getId() const
{
    return textureId;
}

std::string hxe::Texture::getType() const
{
    return type;
}

int hxe::Texture::getBindType() const
{
    return bindType;
}

bool hxe::Texture::loadImage(std::string path, unsigned char** imageData)
{
    unsigned char *data = stbi_load(path.c_str(), &width, &height, &channel, 0);
    if (data)
    {
        switch (channel)
        {
        case 1:
            format = GL_RED;
            break;
        case 3:
            format = GL_RGB;
            break;
        case 4:
            format = GL_RGBA;
            break;
        default:
            format = GL_RGBA;
            break;
        }

        *imageData = data;
        return true;
    }
    else
    {
        std::string logStr = "Texture failed to load at path: ";
        logStr += path;
        LoggerInst->print(logStr.c_str());
        freeImage(data);
        return false;
    }
}

void hxe::Texture::freeImage(unsigned char* imageData)
{
    stbi_image_free(imageData);
}

